package com.divillysausages.dsair.util 
{
	import com.bit101.components.Label;
	import com.bit101.components.Style;
	import com.divillysausages.dsair.DSAir;
	import flash.display.InteractiveObject;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.utils.Dictionary;
	/**
	 * The tooltip class that shows tooltips for the different objects
	 * @author Damian Connolly
	 */
	public class Tooltip 
	{
		
		/********************************************************************/
		
		private static var m_instance:Tooltip 	= null;	// the only instance of the tooltip
		private static var m_creating:Boolean	= false;// are we currently creating the tooltip
		
		/********************************************************************/
		
		/**
		 * Gets the singleton instance of the tooltip
		 */
		public static function get instance():Tooltip
		{
			if ( Tooltip.m_instance == null )
			{
				Tooltip.m_creating = true;
				Tooltip.m_instance = new Tooltip;
				Tooltip.m_creating = false;
			}
			return Tooltip.m_instance;
		}
		
		/********************************************************************/
		
		private var m_messages:Dictionary 	= null; // our messages dictionary
		private var m_tooltip:Label			= null;	// our tooltip label
		
		/********************************************************************/
		
		/**
		 * Creates the Tooltip. As Tooltip is a singleton, don't call this directly; use
		 * the static instance getter instead
		 */
		public function Tooltip() 
		{
			if ( !Tooltip.m_creating )
				throw new Error( "The Tooltip class is a singleton. Use the static instance property instead" );
				
			// create our messages dictionary
			this.m_messages = new Dictionary( true );
			
			// create our tooltip
			this.m_tooltip 							= new Label;
			this.m_tooltip.textField.border 		= true;
			this.m_tooltip.textField.borderColor	= Style.LABEL_TEXT;
			this.m_tooltip.textField.background		= true;
			this.m_tooltip.filters 					= [this.m_tooltip.getShadow( 2.0 )];
				
			// add our listener
			DSAir.stage.addEventListener( MouseEvent.MOUSE_OVER, this._onMouseOver );
		}
		
		/**
		 * Adds a tooltip for an object
		 * @param obj The object we're adding a tooltip for
		 * @param msg The message to show when we mouse over the object
		 */
		public function add( obj:InteractiveObject, msg:String ):void
		{
			if ( !obj.mouseEnabled )
				DSAir.warn( this, "Adding a tooltip '" + msg + "' for " + obj + ", but it's mouseEnabled property is false" );
			this.m_messages[obj] = msg;
		}
		
		/**
		 * Removes a tooltip for an object
		 * @param obj The object to remove the tooltip for
		 */
		public function remove( obj:InteractiveObject ):void
		{
			// check if we're in there
			if ( !( obj in this.m_messages ) )
				return;
				
			// remove it
			this.m_messages[obj] = null;
			delete this.m_messages[obj];
		}
		
		/********************************************************************/
		
		// positions the tooltip
		private function _position():void
		{
			// position to the bottom right
			var x:Number = DSAir.stage.mouseX;
			var y:Number = DSAir.stage.mouseY + 20.0;
			
			// check the bottom
			if ( y + this.m_tooltip.height + 5.0 > DSAir.stage.stageHeight )
				y = DSAir.stage.stageHeight - this.m_tooltip.height - 1.0;
				
			// check the right
			if ( x + this.m_tooltip.width + 5.0 > DSAir.stage.stageWidth )
				x = DSAir.stage.stageWidth - this.m_tooltip.width - 5.0;
				
			// set the position
			this.m_tooltip.x = x;
			this.m_tooltip.y = y;
		}
		
		// hides the tooltip
		private function _hide():void
		{
			// if we're showing, then hide
			if ( this.m_tooltip.parent != null )
				this.m_tooltip.parent.removeChild( this.m_tooltip );
			
			// remove our roll out, click and enter frame listener
			DSAir.stage.removeEventListener( MouseEvent.MOUSE_OUT, this._onMouseOut );
			DSAir.stage.removeEventListener( MouseEvent.CLICK, this._onMouseClick );
			DSAir.stage.removeEventListener( Event.ENTER_FRAME, this._onEnterFrame );
		}
		
		// called when we roll over something
		private function _onMouseOver( e:MouseEvent ):void
		{
			// get our tooltip if we have one
			var tooltip:String = this._getTooltip( e.target as InteractiveObject );
			if ( tooltip == null )
				return;
				
			// get our message
			this.m_tooltip.text = tooltip;
			
			// position it and show
			this._position();
			DSAir.stage.addChild( this.m_tooltip );
			
			// add our roll out and enterframe listener
			DSAir.stage.addEventListener( MouseEvent.MOUSE_OUT, this._onMouseOut );
			DSAir.stage.addEventListener( MouseEvent.CLICK, this._onMouseClick );
			DSAir.stage.addEventListener( Event.ENTER_FRAME, this._onEnterFrame );
		}
		
		// called when we roll out of something
		private function _onMouseOut( e:MouseEvent ):void
		{
			// hide the tooltip
			this._hide();
		}
		
		// called when we click on the object - if the tooltip changes, show it.
		// if it doesn't, then hide the tooltip
		private function _onMouseClick( e:MouseEvent ):void
		{
			// check do we have a new tooltip for the object
			var tooltip:String = this._getTooltip( e.target as InteractiveObject );
			
			// if we don't have a tooltip, or it's the same, just hide
			if ( tooltip == null || tooltip == this.m_tooltip.text )
			{
				this._hide();
				return;
			}
			
			// update the tooltip
			this.m_tooltip.text = tooltip;
			this._position();
		}
		
		// called every frame when we're showing - update the tooltip position
		private function _onEnterFrame( e:Event ):void
		{
			this._position();
		}
		
		// gets the tooltip for an object if there's one
		private function _getTooltip( obj:InteractiveObject ):String
		{
			// if we don't have something save, return null
			if ( !( obj in this.m_messages ) && !( obj.parent in this.m_messages ) )
				return null;
				
			// return our message
			return ( obj in this.m_messages ) ? this.m_messages[obj] : this.m_messages[obj.parent];
		}
		
	}

}